import 'package:ducafe_ui_core/ducafe_ui_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../index.dart';

enum StepperOverlimitType { minus, plus }

typedef StepperOverlimitFunction = void Function(StepperOverlimitType type);

class StepperWidget extends StatefulWidget {
  const StepperWidget({
    super.key,
    this.disableInput = false,
    this.disabled = false,
    this.inputWidth,
    this.max = 100,
    this.min = 0,
    this.scale = WidgetScale.medium,
    this.step = 1,
    this.value = 0,
    this.defaultValue = 0,
    this.onBlur,
    this.onChange,
    this.onOverlimit,
  });

  /// 禁用输入框
  final bool disableInput;

  /// 禁用全部操作
  final bool disabled;

  /// 禁用全部操作
  final double? inputWidth;

  /// 最大值
  final int max;

  /// 最小值
  final int min;

  /// 组件尺寸
  final WidgetScale scale;

  /// 步长
  final int step;

  /// 值
  final int? value;

  /// 默认值
  final int? defaultValue;

  /// 输入框失去焦点时触发
  final VoidCallback? onBlur;

  /// 数值发生变更时触发
  final ValueChanged<int>? onChange;

  /// 数值超出限制时触发
  final StepperOverlimitFunction? onOverlimit;

  @override
  State<StepperWidget> createState() => _StepperWidgetState();
}

class _StepperWidgetState extends State<StepperWidget> {
  late int value;
  late TextEditingController _controller;
  final FocusNode _focusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    value = widget.value ?? widget.defaultValue ?? 0;
    _controller = TextEditingController(text: value.toString());
    _focusNode.addListener(() {
      if (!_focusNode.hasFocus) {
        if (widget.onBlur != null) {
          widget.onBlur!();
        }
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    _focusNode.dispose();
    super.dispose();
  }

  double _getInputWidth() {
    if (widget.inputWidth != null && widget.inputWidth! > 0) {
      return widget.inputWidth!;
    }
    switch (widget.scale) {
      case WidgetScale.small:
        return 34;
      case WidgetScale.medium:
        return 38;
      case WidgetScale.large:
        return 55;
      default:
        return 38;
    }
  }


  double _getTextWidth() {
    var textLength = value.toString().length;
    return textLength < 5 ? 20 : (textLength ) * _getFontSize();
  }

  double _getInputHeight() {
    switch (widget.scale) {
      case WidgetScale.medium:
        return AppSpace.buttonHeight * (1 - 0.2);
      case WidgetScale.small:
        return AppSpace.buttonHeight * (1 - 0.3);
      case WidgetScale.large:
        return AppSpace.buttonHeight * (1 - 0.1);
    }
  }

  double _getFontSize() {
    switch (widget.scale) {
      case WidgetScale.small:
        return 15;
      case WidgetScale.medium:
        return 18;
      case WidgetScale.large:
        return 22;
      default:
        return 18;
    }
  }

  void onAdd() {
    if (value >= widget.max) {
      return;
    }

    if (value + widget.step > widget.max) {
      setState(() {
        value = widget.max;
      });

      if (widget.onOverlimit != null) {
        widget.onOverlimit!(StepperOverlimitType.plus);
      }

      renderNumber();
      return;
    }

    setState(() {
      value += widget.step;
    });

    renderNumber();
  }

  void onReduce() {
    if (value <= widget.min) {
      return;
    }

    if (value - widget.step < widget.min) {
      setState(() {
        value = widget.min;
      });

      if (widget.onOverlimit != null) {
        widget.onOverlimit!(StepperOverlimitType.minus);
      }

      renderNumber();
      return;
    }

    setState(() {
      value -= widget.step;
    });
    renderNumber();
  }

  void renderNumber() {
    _controller.value = TextEditingValue(
        text: value.toString(),
        selection: TextSelection.fromPosition(TextPosition(
          affinity: TextAffinity.downstream,
          offset: value.toString().length,
        )));
    _focusNode.unfocus();

    if (widget.onChange != null) {
      widget.onChange!(value);
    }
  }

  // 减少按钮
  Widget _buildReduceButton(BuildContext context) {
    var colorScheme = context.colors.scheme;

    return ButtonWidget(
      backgroundColor: context.colors.primaryLight,
      icon: Icon(
        Icons.remove,
        color: widget.disabled || value <= widget.min
            ? colorScheme.onPrimary
            : colorScheme.scrim,
      ),
      scale: widget.scale,
      onTap: widget.disabled || value <= widget.min ? null : onReduce,
    );
  }

  // 增加按钮
  Widget _buildAddButton(BuildContext context) {
    var colorScheme = context.colors.scheme;

    return ButtonWidget(
      backgroundColor: context.colors.primaryLight,
      icon: Icon(
        Icons.add,
        color: widget.disabled || value >= widget.max
             ? colorScheme.onPrimary
            : colorScheme.scrim,
      ),
      scale: widget.scale,
      onTap: widget.disabled || value >= widget.max ? null : onAdd,
    );
  }

  // 输入框样式
  Widget _buildInputField(BuildContext context) {
    var colorScheme = context.colors.scheme;

    return Container(
      decoration: const BoxDecoration(border: null),
      child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 4),
          child: ConstrainedBox(
            constraints: BoxConstraints(
                minWidth: _getInputWidth(),
                maxWidth: _getInputWidth() + _getTextWidth()),
            child: Container(
              height: _getInputHeight(),
              alignment: Alignment.center,
              decoration: BoxDecoration(color: context.colors.divider),
              child: Container(
                height: _getFontSize(),
                padding: const EdgeInsets.symmetric(vertical: 2),
                child: TextField(
                  controller: _controller,
                  enabled: !widget.disabled && !widget.disableInput,
                  focusNode: _focusNode,
                  style: TextStyle(
                      fontSize: _getFontSize(),
                      color: widget.disabled ? colorScheme.outline : colorScheme.onSurface),
                  textAlign: TextAlign.center,
                  textAlignVertical: TextAlignVertical.center,
                  keyboardType: TextInputType.number,
                  decoration: const InputDecoration(
                    border: InputBorder.none,
                    isDense: true,
                    contentPadding: EdgeInsets.zero,
                  ),
                  inputFormatters: [
                    FilteringTextInputFormatter.digitsOnly,
                    TextInputFormatter.withFunction((oldValue, newValue) {
                      try {
                        if (newValue.text == '') {
                          setState(() {
                            value = widget.min;
                          });

                          if (widget.onOverlimit != null) {
                            widget.onOverlimit!(StepperOverlimitType.minus);
                          }

                          return newValue.copyWith(
                              text: value.toString(),
                              selection: TextSelection.collapsed(
                                  offset: value.toString().length));
                        }

                        final newNum = int.parse(newValue.text);
                        if (newNum < widget.min) {
                          setState(() {
                            value = widget.min;
                          });
                          if (widget.onOverlimit != null) {
                            widget.onOverlimit!(StepperOverlimitType.minus);
                          }
                        } else if (newNum > widget.max) {
                          setState(() {
                            value = widget.max;
                          });
                          if (widget.onOverlimit != null) {
                            widget.onOverlimit!(StepperOverlimitType.plus);
                          }
                        } else {
                          setState(() {
                            value = newNum;
                          });
                        }

                        return newValue.copyWith(
                            text: value.toString(),
                            selection: TextSelection.collapsed(
                                offset: value.toString().length));
                      } catch (e) {
                        return oldValue;
                      }
                    })
                  ],
                  onChanged: (newValue) {
                    final result = int.parse(newValue);
                    if (widget.onChange != null) {
                      widget.onChange!(result);
                    }
                  },
                ),
              ),
            ),
          )),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        _buildReduceButton(context),
        _buildInputField(context),
        _buildAddButton(context),
      ],
    );
  }
}
